package com.fwzhang.third.collectionframework.collection.set;

import java.io.Serializable;
import java.util.*;

/**
 * HashSet
 */
public class HashSetClass<E> extends AbstractSet<E> implements Set<E>, Serializable, Cloneable {

    /**
     * HashSet本质上使用HashMap存储数据
     * 不过数据存储在HashMap的key上，以保证数据不重复
     * 本质上使用数据的哈希值保证不重复
     * 由于HashMap的key值可以为空，所以HashSet中也可以存储一个空值
     */
    private transient HashMap<E, Object> map;

    /**
     * HashMap的value值，集合中所有数据对应的value都是PRESENT
     */
    private static final Object PRESENT = new Object();

    // constructor

    /**
     * 无参构造函数
     */
    public HashSetClass() {
        map = new HashMap<>();
    }

    /**
     * 0.75 hashMap的默认加载因子
     * 16  hashMap的默认容量
     *
     * @param collection
     */
    public HashSetClass(Collection<? extends E> collection) {
        // collection.size()/0.75f + 1 通过加载因子和当前容量计算map所需要的容量
        // 如果计算出的容量小于16，就取16作为默认容量
        // (int)(collection.size() / 0.75f + 1) 可以看作是进一法的取整，保证默认容量
        map = new HashMap<>((int)Math.max(collection.size()/0.75f + 1, 16));
        addAll(collection);
    }

    /**
     *
     * @param initialCapacity 默认容量
     * @param loadFactor 加载因子
     */
    public HashSetClass(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

    /**
     * 使用默认加载因子 0.75f
     * @param initialCapacity
     */
    public HashSetClass(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

    /**
     * 使用LinkedHashMap存储数据
     * @param initialCapacity 默认容量
     * @param loadFactor 加载因子
     * @param dummy 无实际作用，仅用于标记
     */
    public HashSetClass(int initialCapacity, float loadFactor, boolean dummy) {
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

    // operation

    /**
     * HashSet中对数据的操作都是对map的操作
     */

    @Override
    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }

    @Override
    public int size() {
        return map.size();
    }
}
